package org.example.springboot.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.annotation.Resource;
import org.example.springboot.DTO.BookDTO;
import org.example.springboot.entity.Book;
import org.example.springboot.entity.BookCategory;
import org.example.springboot.exception.ServiceException;
import org.example.springboot.mapper.BookCategoryMapper;
import org.example.springboot.mapper.BookMapper;
import org.example.springboot.mapper.CollectionMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import java.util.stream.Collectors;

/**
 * 图书服务类
 */
@Service
public class BookService {
    @Resource
    private BookMapper bookMapper;
    
    @Resource
    private BookCategoryMapper bookCategoryMapper;
    
    @Resource
    private CollectionMapper collectionMapper;
    
    /**
     * 分页查询图书
     * @param categoryId 分类ID
     * @param keyword 关键词
     * @param currentPage 当前页
     * @param size 每页大小
     * @param orderBy 排序字段
     * @return 分页结果
     */
    public Page<Book> getBooksByPage(Long categoryId, String keyword, Integer status, Integer currentPage, Integer size, String orderBy) {
        // 如果是按收藏数排序，需要特殊处理
        if ("collectionCount".equals(orderBy)) {
            return getBooksByPageWithCollectionCount(categoryId, keyword, currentPage, size);
        }
        
        LambdaQueryWrapper<Book> queryWrapper = new LambdaQueryWrapper<>();
        
        // 添加查询条件
        if (categoryId != null) {
            queryWrapper.eq(Book::getCategoryId, categoryId);
        }
        
        if (StringUtils.isNotBlank(keyword)) {
            queryWrapper.and(wrapper -> 
                wrapper.like(Book::getTitle, keyword)
                    .or()
                    .like(Book::getAuthor, keyword)
                    .or()
                    .like(Book::getDescription, keyword)
            );
        }

        if(status != null) {
            queryWrapper.eq(Book::getStatus, status);
        }
        // 只查询上架的图书
//        queryWrapper.eq(Book::getStatus, 1);
        
        // 根据排序参数进行排序
        switch(orderBy) {
            case "createTime":
                queryWrapper.orderByDesc(Book::getCreateTime);
                break;
            case "avgScore":
                queryWrapper.orderByDesc(Book::getAvgScore);
                break;
            case "borrowedCount":
            default:
                queryWrapper.orderByDesc(Book::getBorrowedCount);
                break;
        }
        
        Page<Book> page = bookMapper.selectPage(new Page<>(currentPage, size), queryWrapper);
        
        // 填充分类名称
        for (Book book : page.getRecords()) {
            BookCategory category = bookCategoryMapper.selectById(book.getCategoryId());
            if (category != null) {
                book.setCategoryName(category.getName());
            }
        }
        
        return page;
    }
    
    /**
     * 根据收藏数排序的分页查询
     * @param categoryId 分类ID
     * @param keyword 关键词
     * @param currentPage 当前页
     * @param size 每页大小
     * @return 分页结果
     */
    private Page<Book> getBooksByPageWithCollectionCount(Long categoryId, String keyword, Integer currentPage, Integer size) {
        // 首先获取所有符合条件的图书
        LambdaQueryWrapper<Book> queryWrapper = new LambdaQueryWrapper<>();
        
        // 添加查询条件
        if (categoryId != null) {
            queryWrapper.eq(Book::getCategoryId, categoryId);
        }
        
        if (StringUtils.isNotBlank(keyword)) {
            queryWrapper.and(wrapper -> 
                wrapper.like(Book::getTitle, keyword)
                    .or()
                    .like(Book::getAuthor, keyword)
                    .or()
                    .like(Book::getDescription, keyword)
            );
        }
        
        // 只查询上架的图书
        queryWrapper.eq(Book::getStatus, 1);
        
        // 获取所有符合条件的图书ID
        List<Long> allBookIds = bookMapper.selectList(queryWrapper)
            .stream()
            .map(Book::getId)
            .toList();
        
        if (allBookIds.isEmpty()) {
            return new Page<>(currentPage, size, 0);
        }
        
        // 查询这些图书的收藏次数
        List<Map<String, Object>> collectionData = collectionMapper.getHotCollectionBooksWithIds(allBookIds);
        
        // 构建排序后的图书ID列表
        List<Long> sortedBookIds = new java.util.ArrayList<>(allBookIds);
        
        // 先按收藏次数排序（有收藏的）
        List<Long> collectedBookIds = collectionData.stream()
            .map(map -> Long.valueOf(map.get("bookId").toString()))
            .toList();
        
        // 然后是没有收藏的
        List<Long> uncollectedBookIds = allBookIds.stream()
            .filter(id -> !collectedBookIds.contains(id))
            .toList();
        
        // 合并排序后的列表
        sortedBookIds.clear();
        sortedBookIds.addAll(collectedBookIds);
        sortedBookIds.addAll(uncollectedBookIds);
        
        // 分页逻辑
        int total = sortedBookIds.size();
        int startIndex = (currentPage - 1) * size;
        int endIndex = Math.min(startIndex + size, total);
        
        // 处理超出范围的情况
        if (startIndex >= total) {
            return new Page<>(currentPage, size, total);
        }
        
        // 获取当前页的图书ID
        List<Long> pageBookIds = sortedBookIds.subList(startIndex, endIndex);
        
        // 查询当前页的图书详情
        List<Book> pageBooks = bookMapper.selectList(
            new LambdaQueryWrapper<Book>()
                .in(Book::getId, pageBookIds)
        );
        
        // 按照排序ID的顺序对图书进行排序
        pageBooks.sort((b1, b2) -> {
            int index1 = pageBookIds.indexOf(b1.getId());
            int index2 = pageBookIds.indexOf(b2.getId());
            return Integer.compare(index1, index2);
        });
        
        // 填充分类名称和收藏次数
        Map<Long, Integer> bookIdToCountMap = collectionData.stream()
            .collect(java.util.stream.Collectors.toMap(
                map -> Long.valueOf(map.get("bookId").toString()),
                map -> Integer.valueOf(map.get("count").toString())
            ));
        
        for (Book book : pageBooks) {
            // 填充分类名称
            BookCategory category = bookCategoryMapper.selectById(book.getCategoryId());
            if (category != null) {
                book.setCategoryName(category.getName());
            }
            
            // 填充收藏次数
            book.setCollectionCount(bookIdToCountMap.getOrDefault(book.getId(), 0));
        }
        
        // 创建并返回分页结果
        Page<Book> page = new Page<>(currentPage, size, total);
        page.setRecords(pageBooks);
        
        return page;
    }
    
    /**
     * 根据ID获取图书
     * @param id 图书ID
     * @return 图书实体
     */
    public Book getBookById(Long id) {
        Book book = bookMapper.selectById(id);
        if (book == null) {
            throw new ServiceException("图书不存在");
        }
        
        // 填充分类名称
        BookCategory category = bookCategoryMapper.selectById(book.getCategoryId());
        if (category != null) {
            book.setCategoryName(category.getName());
        }
        
        return book;
    }
    
    /**
     * 添加图书
     * @param bookDTO 图书信息
     * @return 图书ID
     */
    @Transactional(rollbackFor = Exception.class)
    public Long addBook(BookDTO bookDTO) {
        // 检查ISBN是否已存在
        if (bookMapper.selectOne(new LambdaQueryWrapper<Book>()
                .eq(Book::getIsbn, bookDTO.getIsbn())) != null) {
            throw new ServiceException("ISBN已存在");
        }
        
        // 检查分类是否存在
        if (bookDTO.getCategoryId() != null) {
            if (bookCategoryMapper.selectById(bookDTO.getCategoryId()) == null) {
                throw new ServiceException("所选分类不存在");
            }
        }
        
        Book book = new Book();
        BeanUtils.copyProperties(bookDTO, book);
        
        // 设置默认值
        book.setBorrowedCount(0);
        book.setAvgScore(java.math.BigDecimal.valueOf(0.0));
        book.setStatus(1); // 默认上架
        
        if (bookMapper.insert(book) <= 0) {
            throw new ServiceException("添加图书失败");
        }
        
        return book.getId();
    }
    
    /**
     * 更新图书
     * @param id 图书ID
     * @param bookDTO 图书信息
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateBook(Long id, BookDTO bookDTO) {
        // 检查图书是否存在
        if (bookMapper.selectById(id) == null) {
            throw new ServiceException("要更新的图书不存在");
        }
        
        // 检查ISBN是否与其他图书重复
        if (bookDTO.getIsbn() != null) {
            Book existBook = bookMapper.selectOne(
                new LambdaQueryWrapper<Book>()
                    .eq(Book::getIsbn, bookDTO.getIsbn())
            );
            if (existBook != null && !existBook.getId().equals(id)) {
                throw new ServiceException("ISBN已被其他图书使用");
            }
        }
        
        // 检查分类是否存在
        if (bookDTO.getCategoryId() != null) {
            if (bookCategoryMapper.selectById(bookDTO.getCategoryId()) == null) {
                throw new ServiceException("所选分类不存在");
            }
        }
        
        Book book = new Book();
        BeanUtils.copyProperties(bookDTO, book);
        book.setId(id);
        
        if (bookMapper.updateById(book) <= 0) {
            throw new ServiceException("更新图书失败");
        }
    }
    
    /**
     * 删除图书
     * @param id 图书ID
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteBook(Long id) {
        // 检查图书是否存在
        if (bookMapper.selectById(id) == null) {
            throw new ServiceException("要删除的图书不存在");
        }
        
        // 这里应该检查图书是否被借阅、收藏等，如果有关联数据应该禁止删除或者做级联删除
        // 暂时简化处理，直接删除
        
        if (bookMapper.deleteById(id) <= 0) {
            throw new ServiceException("删除图书失败");
        }
    }
    
    /**
     * 更新图书状态
     * @param id 图书ID
     * @param status 状态(0:下架,1:上架)
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateBookStatus(Long id, Integer status) {
        Book book = bookMapper.selectById(id);
        if (book == null) {
            throw new ServiceException("图书不存在");
        }
        
        book.setStatus(status);
        System.out.printf("<UNK>%s<UNK>%s<UNK>\n", id, status);
        if (bookMapper.updateById(book) <= 0) {
            throw new ServiceException("更新图书状态失败");
        }
    }
    
    /**
     * 获取热门图书
     * @param limit 数量限制
     * @return 热门图书列表
     */
    public List<Book> getHotBooks(Integer limit) {
        LambdaQueryWrapper<Book> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Book::getStatus, 1)
                    .orderByDesc(Book::getBorrowedCount, Book::getAvgScore)
                    .last("LIMIT " + limit);
        
        List<Book> books = bookMapper.selectList(queryWrapper);
        
        // 填充分类名称
        for (Book book : books) {
            BookCategory category = bookCategoryMapper.selectById(book.getCategoryId());
            if (category != null) {
                book.setCategoryName(category.getName());
            }
        }
        
        return books;
    }
    
    /**
     * 获取最新图书
     * @param limit 数量限制
     * @return 最新图书列表
     */
    public List<Book> getNewBooks(Integer limit) {
        LambdaQueryWrapper<Book> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Book::getStatus, 1)
                    .orderByDesc(Book::getCreateTime)
                    .last("LIMIT " + limit);
        
        List<Book> books = bookMapper.selectList(queryWrapper);
        
        // 填充分类名称
        for (Book book : books) {
            BookCategory category = bookCategoryMapper.selectById(book.getCategoryId());
            if (category != null) {
                book.setCategoryName(category.getName());
            }
        }
        
        return books;
    }
    
    /**
     * 获取热门收藏图书
     * @param limit 数量限制
     * @return 热门收藏图书列表
     */
    public List<Book> getHotCollectionBooks(Integer limit) {
        // 获取热门收藏图书ID及收藏次数
        List<Map<String, Object>> hotCollectionData = collectionMapper.getHotCollectionBooks(limit);
        
        // 如果没有收藏数据，返回空列表
        if (hotCollectionData.isEmpty()) {
            return List.of();
        }
        
        // 提取图书ID列表
        List<Long> bookIds = hotCollectionData.stream()
                .map(map -> Long.valueOf(map.get("bookId").toString()))
                .toList();
        
        // 查询这些图书详情
        LambdaQueryWrapper<Book> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(Book::getId, bookIds)
                    .eq(Book::getStatus, 1);
        
        List<Book> books = bookMapper.selectList(queryWrapper);
        
        // 按照收藏次数排序
        books.sort((b1, b2) -> {
            int index1 = bookIds.indexOf(b1.getId());
            int index2 = bookIds.indexOf(b2.getId());
            return Integer.compare(index1, index2);
        });
        
        // 填充分类名称和收藏次数
        for (Book book : books) {
            // 填充分类名称
            BookCategory category = bookCategoryMapper.selectById(book.getCategoryId());
            if (category != null) {
                book.setCategoryName(category.getName());
            }
            
            // 填充收藏次数
            int index = bookIds.indexOf(book.getId());
            if (index >= 0 && index < hotCollectionData.size()) {
                Map<String, Object> data = hotCollectionData.get(index);
                book.setCollectionCount(Integer.valueOf(data.get("count").toString()));
            }
        }
        
        return books;
    }
    
    /**
     * 获取评分最高图书
     * @param limit 数量限制
     * @return 评分最高图书列表
     */
    public List<Book> getTopRatedBooks(Integer limit) {
        LambdaQueryWrapper<Book> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Book::getStatus, 1)
                    .orderByDesc(Book::getAvgScore)
                    .last("LIMIT " + limit);
        
        List<Book> books = bookMapper.selectList(queryWrapper);
        
        // 填充分类名称
        for (Book book : books) {
            BookCategory category = bookCategoryMapper.selectById(book.getCategoryId());
            if (category != null) {
                book.setCategoryName(category.getName());
            }
        }
        
        return books;
    }
} 